package com.lsh.oms.core.service.tool;

import com.lsh.base.lang.Numbers;
import com.lsh.base.lang.json.Jsons;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Criteria {

    private static final Logger LOGGER = LoggerFactory.getLogger(Criteria.class);

    private MultivaluedMap<String, String> criteria = new MultivaluedHashMap<>();

    public Criteria() {
    }

    public Criteria(MultivaluedMap<String, String> parameters) {
        for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
            criteria.put(formatKey(entry.getKey()), value(entry.getValue()));
        }
    }

    private List<String> value(List<String> value) {
        if (value != null && value.size() == 1 && value.get(0) != null && value.get(0).contains(",")) {
            return Stream.of(value.get(0).split(",")).collect(Collectors.toList());
        } else {
            return value;
        }
    }

    public static Criteria of(UriInfo uriInfo) {
        Criteria criteria = new Criteria(uriInfo.getQueryParameters());
        Optional.ofNullable(MDC.get("vender-id")).map($ -> StringUtils.split((String) $, ",")).ifPresent($ -> Stream.of($).filter(Numbers::isNaturalNumber).forEach($$ -> criteria.add("vender_id", $$)));
        LOGGER.info("criteria: {}", criteria);
        return criteria;
    }

    public static Criteria of(String k, String v) {
        Criteria criteria = new Criteria();
        criteria.add(k, v);
        return criteria;
    }

    public static Criteria of(String k1, String v1, String k2, String v2) {
        Criteria criteria = of(k1, v1);
        criteria.add(k2, v2);
        return criteria;
    }

    public static Criteria of(String k1, String v1, String k2, String v2, String k3, String v3) {
        Criteria criteria = of(k1, v1, k2, v2);
        criteria.add(k3, v3);
        return criteria;
    }

    public static Criteria of(String k1, String v1, String k2, String v2, String k3, String v3, String k4, String v4) {
        Criteria criteria = of(k1, v1, k2, v2, k3, v3);
        criteria.add(k4, v4);
        return criteria;
    }

    public static Criteria empty() {
        return new Criteria();
    }

    public MultivaluedMap<String, String> getCriteria() {
        return criteria;
    }

    public List<String> get(String key) {
        return criteria.get(formatKey(key));
    }

    public String getFirst(String key) {
        return criteria.getFirst(formatKey(key));
    }

    public void add(String key, String value) {
        criteria.add(formatKey(key), value);
    }

    public void replace(String key, String value) {
        criteria.remove(formatKey(key));
        criteria.addFirst(formatKey(key), value);
    }

    public void remove(String key) {
        criteria.remove(formatKey(key));
    }

    private String formatKey(String key) {
        return key.replace("-", "_");
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        criteria.forEach((key, value) -> string.append(key).append(": ").append(Jsons.toJsonString(value)).append(", "));
        return string.toString();
    }
}
